了解JS对象的属性的特性 | 您所在的位置:网站首页 › js 修改对象的属性名字 › 了解JS对象的属性的特性 |
一 对象属性的特性
对于对象中的属性,除了可以对其赋值以外,每一个属性的内部都包含有一些内部特性来描述属性自身的特征的。 这些内部特性,开发者是无法直接访问的,只能通过 Object.defineProperty() 这个函数来对其进行修改。 不同的对象属性又有不同的内部特性,这里分开来介绍。对象的属性分两种:数据属性和访问器属性。 1 数据属性数据属性就是最普通的属性,包含一个保存数据的位置。值都在同一个地方读写,比如这里的 name 就是一个数据属性: 这种属性有四个特性描述他们的行为: 1). configurable “可配置的” 默认值:true 作用: 是否可以通过 delete 删除并重新定义 是否可以修改其特性 是否可以把它改为访问器属性。 解释: 如果把 configurable 设置成 false,就意味着这个属性不能在对象上删除。非严格模式下对这个属性调用 delete 没有效果(返回 false),严格模式下会抛出错误。 而且,当一个属性被设置为不可配置之后,就不能再设置回可配置的了,也无法修改其他内部特性,因为 Object.defineProperty() 无法对 configurable 值为 false 的属性进行修改。 2). enumerable “可列举的” 默认值:true 作用:是否可以通过 for-in 循环返回。(for-in 循环可以列举对象的属性) 3). writable “可写的” 默认值:true 作用:它的值(也就是👇下面的 value 属性)是否可被修改。 4). value “值” 默认值:undefined 作用:属性实际的值。 在👆上面 person.name 这个示例属性中,它的 value 就为 "对象属性"。 1.1 修改方法Object.defineProperty() 需要传入三个参数,第一个是需要修改属性的对象,第二个是属性的名称,第三个是需要修改的特性的集合。 例如我想把 name 属性修改为不可枚举且不可修改: 函数的第三个参数只需传入需要修改的特性和值即可,对于没传入的特性,比如上面没有传入的 configurable 和 value 这两个特性将会保持原有值不变。 如果第二个参数传入的属性名是对象上没有的属性,就会为那个对象添加一个属性。例如: 2访问器属性访问器属性不包含数据值,取而代之的是一个 getter 函数和一个 setter 函数,不过这两个函数都不是必须的。 在读取访问器属性时,会调用 getter 函数,并返回函数的返回值。 在写入访问器属性的时候,会调用 setter 函数,并传入新值,由 setter 函数来决定如何处理这个新值。 访问器属性也有四个特性,其中 configurable 和 enumerable 特性和数据属性是一样的,不同的是另外两个特性被 get 和 set 取代: 1). configurable “可配置的” 默认值:true 作用:👆同数据属性一样。 2). enumerable “可列举的” 默认值:true 作用:👆同数据属性一样。 3). get “获取函数” 默认值:undefined 作用:获取函数,在读取属性时调用。 4). set “设置函数” 默认值:undefined 作用:设置函数,在写入属性时调用。 2.1修改方法同数据属性类似,访问器属性的特性也是通过 Object.defineProperty() 来定义的: 二.对象序列化? 1).什么是对象序列化?对象序列化是指将对象的状态转换为字符串; 序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程; 2).为什么会有对象序列化?当这句代码运行时,对象obj的内容会存储在一块内存中,而obj本身存储的只是这块内存的地址的映射而已。简单的说,对象obj就是我们的程序在电脑通电时在内存中维护的一种东西,如果我们程序停止了或者电脑断电了,对象obj将不复存在。那么如何把对象obj的内容保存在磁盘上呢(也就是说在没电时继续保留着)?这时就需要把对象obj序列化,也就是说把obj的内容转换成一个字符串的形式,然后再保存在磁盘上。另外,我们又怎么通过HTTP协议把对象obj的内容发送到客户端呢?没错,还是需要先把对象obj序列化,然后客户端根据接收到的字符串再反序列化(也就是将字符串还原为对象)解析出相应的对象。这也正是”百度百科—序列化“中描述的两个作用——存储、传输。 1 JSON.stringify() 1.1.简介序列化原始值、对象或数组 1.2.概要JSON.stringify(o[, filter][, indent]) 1.3.参数o,要转换成JSON字符串的原始值、对象或数组 filter,可选参数,一个数组或函数 indent,可选参数,一个数值或一个字符串 1.4.返回JSON格式的字符串,代表o的值,同时通过了filter的过滤,以及根据indent进行了格式化 1.5.描述①当对象o自身带有toJSON()方法时,JSON.stringify()会调用o的toJSON()方法,并使用该方法的返回值而不是该对象本身进行字符串化; ②如果filter存在且是一个函数,那么该函数的返回值将会作为JSON.stringify()方法的返回值。并且该函数接收两个参数,第一个参数是一个空字符串,第二个参数就是对象o。这里,大家也可以参考Douglas Crockford为 ES3 环境使用JSON写的json2: ③如果filter存在且是一个字符串数组(如果数组中包含数字,数字会自动转化为字符串),那么对象o的某些属性名如果不在这个数组中,则序列化时会将这些属性省略,且返回的字符串中属性的顺序会与该数组中属性的顺序一致; ④JSON.stringify()返回的通常是不带任何空格或换行符的字符串。如果想输出可读性更好的字符串,需要指定第三个参数。如果指定的第三个参数是介于1~10之间的值,则JSON.stringify()会在每一“层级”的输出插入换行符和指定个数的空格。如果指定的第三个参数是非空字符串,则JSON.stringify()会插入换行符和该字符串(只取前十个字符)来缩进层级; 2 JSON.parse() 2.1.简介解析JSON格式的字符串 2.2.概要JSON.parse(s[, reviver]) 2.3.参数s,要解析的字符串 reviver,可选参数,用来转换解析值的可选函数 2.4.返回一个对象、数组或原始值。该返回值是从s中解析的(还有可能被reviver修改过); 2.5.描述①如果指定了reviver函数,该函数会为从s中解析的每一个原始值(不是包含这些原始值的对象或数组)调用一次。调用reviver时带有两个参数,第一个参数是属性名——对象的属性名或转换成字符串的数组序号,第二个参数是对象属性或数组元素的原始值。并且,reviver函数的返回值将作为JSON.parse()的返回值; 三 对象原型链1 函数与对象的关系 函数是对象,对象都是通过函数创建的。 函数与对象并不是简单的包含与被包含的关系。 2 原型的类别 显示原型:prototype,是每个函数function独有的属性。 隐式原型: proto,是每个对象都具有的属性。 3 原型和原型链 原型:一个函数可以看成一个类,原型是所有类都有的一个属性,原型的作用就是给这个类的一个对象都添加一个统一的方法。 原型链:每个对象都有一个__proto__,它指向它的prototype原型对象;它的prototype原型对象又有一个__proto__指向它的prototype原型对象,就这样层层向上直到最终找到顶级对象Object的prototype,这个查询路径就是原型链。 四 对象的数据存储1 对象数据存储在堆栈中。栈的数据读取,写入速度快,但是存储的内容较少。堆的读取和写入速度慢,但是存储的内容多。举个例子来说就像电脑中内存和硬盘,内存就像栈,需要经常获取,写入速度比较快时需要写道内存也就是需要存储在栈中的数据,其中字符型,数值型,布尔型,undefined存储在栈中,栈中,一旦该变量不再使用时就会被清理掉。而对象是存储在堆中,当堆中有对象时,它会相对应内存中有一个存储的地址,在栈中obj存储了在堆中数据的地址,当调用数据时,去堆中调取对应堆中的数据的地址获取出来。 2 如上,代码执行时一行接着一行,先创建一个对象,打印在控制台后,把obj的a值改为10,在控制台点开对象前的箭头时,obj的a值却已经更改为10,这就是我们在打印后去更改,可在去点击箭头时,才会去堆中对应地址获取数据,所以获取的就是最新的数据。 3 如上,如果将obj赋值给obj1,就相当于把obj在堆中存储数据的地址给到obj1,obj1更改对象原有的数据时,obj也会跟着更改 4 如上,如果将obj赋值给obj2,但在obj生成新对象时,就会在栈中创建一个新的存储数据的地址,所以后更改对象数据时更改到就是新的存储数据的地址中,而obj2的存储数据地址还是原来的对象地址,所以打印后只有对象在没有生成新对象之前的堆中地址存储的数据。 5 如上,如果将obj赋值给obj3,两个对象在堆中存储地址相同时,我们两个对象都不想去使用时,把堆中对象存储的地址丢弃时,该数据在堆中存在,并且找不到它,当如此情况非常多时,称之为内存泄漏,会造成卡死,想要解决掉这个问题, 就需要把对象堆中存储数据地址的所有引用对象全部先设置为null,之后再去重新赋值 |
CopyRight 2018-2019 实验室设备网 版权所有 |